package com.cqut.service.impl;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.annotation.Resource;
import javax.servlet.ServletContext;

import com.cqut.dto.DownloadFileDTO;
import org.springframework.stereotype.Service;

import com.cqut.model.FileManager;
import com.cqut.service.IFileManagerService;
import com.cqut.dao.FileManagerMapper;
import com.cqut.util.SqlUtil;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

@Service
public class FileManagerService implements IFileManagerService {
    @Resource(name="fileManagerMapper")
    private FileManagerMapper fileManagerMapper;

    private String fileRootPath;

    public String getFileRootPath() {
        return fileRootPath;
    }

    public void setFileRootPath(String fileRootPath) {
        this.fileRootPath = this.getClass().getClassLoader().getResource("/").getPath() + fileRootPath;
    }

    @Override
    public boolean save(FileManager fileManager) {
        return fileManagerMapper.insert(fileManager) > 0;
    }

    @Override
    public boolean update(FileManager fileManager) {
        return fileManagerMapper.updateByPrimaryKeySelective(fileManager) >= 0;
    }

    @Override
    public boolean delete(String fileId) {
        return fileManagerMapper.deleteByPrimaryKey(fileId) > 0;
    }

    @Override
    public boolean batchDelete(String[] primaryKeys) {
        return fileManagerMapper.deleteByPrimaryKeys(primaryKeys) > 0;
    }

    @Override
    public FileManager findModel(String fileId) {
        return fileManagerMapper.selectByPrimaryKey(fileId);
    }

    @Override
    public FileManager findModel(String fileId, String[] parameters) {
        return fileManagerMapper.findModel(fileId, SqlUtil.formatParameters(parameters));
    }

    public Map<String, Object> findMap(String fileId) {
        String[][] parameters = {{"file_id", "fileId"}, {"file_path", "filePath"}};
        return this.findMap(fileId, parameters);
    }

    public Map<String, Object> findMap(String fileId, String[][] parameters) {
        return fileManagerMapper.findMap(fileId, SqlUtil.formatParametersForAlias(parameters));
    }

    @Override
    public List<FileManager> loadModels() {
        return this.loadModels(null, null, null, null, -1, -1);
    }

    @Override
    public List<FileManager> loadModels(String condition, Object[] values, String order, String sort, int curPage, int limit) {
        return this.loadModels(null, condition, values, order, sort, curPage, limit);
    }

    @Override
    public List<FileManager> loadModels(String[] parameters, String condition, Object[] values, String order, String sort, int curPage, int limit) {
        return fileManagerMapper.loadModels(SqlUtil.formatParameters(parameters), SqlUtil.fillCondition(condition, values), order, sort, SqlUtil.getOffset(curPage, limit), limit);
    }

    @Override
    public List<Map<String, Object>> loadMaps() {
        String[][] parameters = {{"file_id", "fileId"}, {"file_path", "filePath"}};
        return this.loadMaps(parameters, null, null, null, null, -1, -1);
    }

    @Override
    public List<Map<String, Object>> loadMaps(String condition, Object[] values, String order, String sort, int curPage, int limit) {
        String[][] parameters = {{"file_id", "fileId"}, {"file_path", "filePath"}};
        return this.loadMaps(parameters, condition, values, order, sort, curPage, limit);
    }

    @Override
    public List<Map<String, Object>> loadMaps(String[][] parameters, String condition, Object[] values, String order, String sort, int curPage, int limit) {
        return fileManagerMapper.loadMaps(SqlUtil.formatParametersForAlias(parameters), SqlUtil.fillCondition(condition, values), order, sort, SqlUtil.getOffset(curPage, limit), limit);
    }

    @Override
    public long count() {
        return this.count(null, false);
    }

    @Override
    public long count(String condition, Object[] values) {
        return this.count(null, condition, values, false);
    }

    @Override
    public long count(String[] parameters, boolean isDistinct) {
        return this.count(parameters, null, null, isDistinct);
    }

    @Override
    public long count(String[] parameters, String condition, Object[] values, boolean isDistinct) {
        return fileManagerMapper.count(SqlUtil.formatParameters(parameters), SqlUtil.fillCondition(condition, values), isDistinct);
    }

    public Map<String, Object> uploadFile(CommonsMultipartFile file) {
        String fileName = file.getOriginalFilename();

        // 文件命名方式：当前时间 + 原来的文件名
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
        String time = sdf.format(new Date());
        String newFileName = time + fileName.substring(fileName.lastIndexOf("."));

        // 文件的相对路径
        String newFilePath = getDatePath() + File.separator + newFileName;
        // 新文件
        File newFile = new File(fileRootPath + newFilePath);
        // 判断目标文件所在目录是否存在
        if( !newFile.getParentFile().exists()) {
            // 如果目标文件所在的目录不存在，则创建父目录
            newFile.getParentFile().mkdirs();
        }

        try {
            file.transferTo(newFile);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        String fileId = String.valueOf(System.currentTimeMillis());
        FileManager fileManager = new FileManager(fileId, fileName, file.getContentType(), newFilePath);

        return fileManagerMapper.insert(fileManager) > 0 ?
                createFileInfo(fileId, fileName, file.getContentType()) : null;
    }



    // 获取文件存放的路径
    private String getDatePath() {
        Calendar calendar = Calendar.getInstance();
        StringBuilder sb = new StringBuilder();
        sb.append("/");
        sb.append(calendar.get(Calendar.YEAR));
        sb.append("/");
        sb.append(calendar.get(Calendar.MONTH) + 1);
        sb.append("/");
        sb.append(calendar.get(Calendar.DATE));
        return sb.toString();
    }

    // 获取返回的文件的信息map
    private Map<String, Object> createFileInfo(String fileId, String fileName, String fileType) {
        Map<String, Object> rs = new HashMap<String, Object>();

        rs.put("fileId", fileId);
        rs.put("fileName", fileName);
        rs.put("fileType", fileType);

        return rs;
    }


    @Override
    public DownloadFileDTO downloadFile(String fileId) {
        FileManager fileManger = fileManagerMapper.selectByPrimaryKey(fileId);

        if (fileManger == null)
            return null;

        String filePath = fileRootPath + fileManger.getFilePath();

        try (InputStream bis = new BufferedInputStream(new FileInputStream(new File(filePath)))) {
            byte[] content = new byte[bis.available()];
            bis.read(content);

            DownloadFileDTO dto = new DownloadFileDTO(content, fileManger.getFileName(), fileManger.getFileType());
            return dto;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }


}
